function Request(op) {
    this.url = op.url;
    this.method = op.method || 'get';
    this.data = op.data;
    this.success = op.success;
    this.fail = op.fail;
    this.headers = op.headers || {};
}

Request.prototype = {
    send: function () {
        var _this = this;
        var xhr = new XMLHttpRequest();
        xhr.open(this.method, this.url, true);
        for (var name in this.headers) {
            if (this.headers.hasOwnProperty(name)) {
                xhr.setRequestHeader(name, this.headers[name]);
            }
        }
        xhr.onreadystatechange = function () {
            if (xhr.readyState === XMLHttpRequest.DONE) {
                if (xhr.status === 200) {
                    var data;
                    try {
                        data = JSON.parse(xhr.responseText);
                    } catch (e) {
                        data = xhr.responseText;
                    }
                    _this.success(data);
                } else {
                    _this.fail(xhr.status, xhr.responseText);
                }
            }
        };
        xhr.send(this.data);
    }
};

function findEle(id) {
    return document.getElementById(id);
}

function isIp(str) {
    return str.match(/^(\d{1,3}\.){3}\d{1,3}$/);
}

function isBlank(str) {
    return str.trim() === '';
}

function Mask() {
    this.mask = findEle('mask');
}

Mask.prototype = {
    show: function (show) {
        this.mask.style.display = show ? 'flex' : 'none';
    }
};

function Form(mask) {
    this.mask = mask;
}

Form.prototype = {
    init: function () {
        this.net = {
            ip: findEle('net-ip'),
            nm: findEle('net-netmask'),
            gw: findEle('net-gateway'),
            dns: findEle('net-dns'),
            dhcp: findEle('net-dhcp'),
            ssid: findEle('wifi-ssid'),
            passwd: findEle('wifi-password')
        };
        this.api = {
            curl: findEle('api-curl'),
            type: findEle('api-type'),
            wid: findEle('api-wid'),
            eid: findEle('api-eid'),
        };
        var _this = this;
        findEle('btn-apply').onclick = function () {
            _this.onCommit()
        }
    },
    opMask: function (op) {
        this.mask.show(op);
    },
    loadData: function () {
        var net = this.net;
        var api = this.api;
        var _this = this;
        new Request({
            url: 'config.json',
            method: 'GET',
            success: function (data) {
                console.log('hallo', net, data);
                net.ip.value = data.net.ip;
                net.nm.value = data.net.netmask;
                net.gw.value = data.net.gateway;
                net.dns.value = data.net.dns;
                net.dhcp.checked = data.net.dhcp;
                net.ip.value = data.net.ip;
                net.ssid.value = data.net.ap.ssid;
                net.passwd.value = data.net.ap.password;
                api.curl.value = data.api.commitUrl;
                api.type.value = data.api.paramsType;
                api.eid.value = data.api.entityId;
                api.wid.value = data.api.warehouseId;
                _this.opMask(false);
            },
            fail: function (code, resp) {
                console.log(code, resp);
                alert('ErrorCode=' + code + '; data=' + resp);
            }
        }).send();
    },
    valiadate: function () {
        var net = this.net;
        var api = this.api;
        if (!isIp(net.ip.value)) {
            alert('Invalidate Network IP');
            return false;
        }
        if (!isIp(net.nm.value)) {
            alert('Invalidate Network Netmask');
            return false;
        }
        if (!isIp(net.gw.value)) {
            alert('Invalidate Network Gateway');
            return false;
        }
        if (!isIp(net.dns.value)) {
            alert('Invalidate Network DNS');
            return false;
        }
        if (isBlank(net.ssid.value)) {
            alert('Invalidate WIFI SSID');
            return false;
        }
        if (isBlank(api.curl.value)) {
            alert('Invalidate API CommitURL');
            return false;
        }
        if (isBlank(api.type.value)) {
            alert('Invalidate API Params Type');
            return false;
        }
        if (isBlank(api.wid.value)) {
            alert('Invalidate API Warehouse ID');
            return false;
        }
        if (isBlank(api.eid.value)) {
            alert('Invalidate API Entity ID');
            return false;
        }
        return true;
    },
    onCommit: function () {
        var net = this.net;
        var api = this.api;
        if (!this.valiadate()) {
            return false;
        }
        var data = {
            net: {
                ip: net.ip.value,
                netmask: net.nm.value,
                gateway: net.gw.value,
                dns: net.dns.value,
                dhcp: net.dhcp.checked,
                ap: {
                    ssid: net.ssid.value,
                    password: net.passwd.value,
                }
            },
            api: {
                commitUrl: api.curl.value,
                paramsType: api.type.value,
                warehouseId: api.wid.value,
                entityId: api.eid.value,
            }
        };
        var body = JSON.stringify(data);
        console.log('Apply Configuration', data);
        this.opMask(true);
        var _this = this;
        new Request({
            url: 'config',
            method: 'POST',
            data: body,
            success: function (res) {
                _this.opMask(false);
                if (res.code === 200) {
                    alert('Saved successfully! Please restart to apply changes!');
                } else {
                    alert(res.msg ? res.msg : res)
                }
            },
            fail: function (code, resp) {
                _this.opMask(false);
            }
        }).send()
    }
};

function UpgradeForm(mask) {
    this.mask = mask;
    this.file = null;
}

UpgradeForm.prototype = {
    init: function () {
        this.form = findEle('upgrade-form');
        this.fileInput = findEle('upgrade-file');
        this.fileNameInput = findEle('upgrade-file-name')
        var _this = this;
        this.fileInput.onchange = function (e) {
            _this.onFileInputChange(e)
        };
        this.form.onsubmit = function (e) {
            _this.onFormSubmit(e);
        }
    },
    onFileInputChange: function (e) {
        var files = e.target.files;
        if (!files || !files.length) {
            alert('Please choose a file!')
            this.file = null;
            return;
        }
        var file = files[0];
        this.fileNameInput.value = file.name;
        this.file = file;
    },
    onFormSubmit: function (e) {
        e.preventDefault();
        if (!this.file) {
            alert('Please choose a file!');
            return;
        }
        if (isBlank(this.fileNameInput.value)) {
            alert('Please enter filename!');
            return;
        }
        var reader = new FileReader();
        const _this = this;
        reader.onload = function (e) {
            _this.fileContent = e.target.result;
            _this.uploadFile();
        };
        reader.readAsText(this.file);
        return false;
    },
    uploadFile: function () {
        var fileName = this.fileNameInput.value;
        var fileContent = this.fileContent;
        this.mask.show(true);
        var _this = this;
        new Request({
            url: '/upgrade',
            method: 'post',
            data: fileContent,
            headers: {
                'X-FileName': fileName,
            },
            success: function (data) {
                alert('Upgrade success!' + data);
                console.log(data);
                _this.mask.show(false);
            },
            fail: function (code, resp) {
                console.error('Error on upgrade', code, resp);
                alert('Error: code=' + code + ';resp=[' + resp + ']');
                _this.mask.show(false);
            }
        }).send();
    }
};

window.onload = function () {
    var mask = new Mask();
    var form = new Form(mask);
    form.init();
    form.loadData();
    var upgradeForm = new UpgradeForm(mask);
    upgradeForm.init();
};
